#ifndef TGALOADER_H_
#define TGALOADER_H_
#include "gltools.h"
//
#pragma pack(1)
typedef struct
{
    GLbyte	identsize;              // Size of ID field that follows header (0)
    GLbyte	colorMapType;           // 0 = None, 1 = paletted
    GLbyte	imageType;              // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle
    unsigned short	colorMapStart;          // First colour map entry
    unsigned short	colorMapLength;         // Number of colors
    unsigned char 	colorMapBits;   // bits per palette entry
    unsigned short	xstart;                 // image x origin
    unsigned short	ystart;                 // image y origin
    unsigned short	width;                  // width in pixels
    unsigned short	height;                 // height in pixels
    GLbyte	bits;                   // bits per pixel (8 16, 24, 32)
    GLbyte	descriptor;             // image descriptor
} TGAHEADER;
#pragma pack(8)
//
//////////////////////////////////////////////////////////////////////
//// Allocate memory and load targa bits. Returns pointer to new buffer,
//// height, and width of texture, and the OpenGL format of data.
//// Call free() on buffer when finished!
//// This only works on pretty vanilla targas... 8, 24, or 32 bit color
//// only, no palettes, no RLE encoding.
//GLbyte *gltReadTGABits(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat)
//{
//    FILE *pFile;			// File pointer
//    TGAHEADER tgaHeader;		// TGA file header
//    unsigned long lImageSize;		// Size in bytes of image
//    short sDepth;			// Pixel depth;
//    GLbyte	*pBits = NULL;          // Pointer to bits
//    
//    // Default/Failed values
//    *iWidth = 0;
//    *iHeight = 0;
//    *eFormat = GL_RGB;
//    *iComponents = GL_RGB;
//    
//    // Attempt to open the fil
//    pFile = fopen(szFileName, "rb");
//    if(pFile == NULL)
//        return NULL;
//	
//    // Read in header (binary)
//    fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, pFile);
//	
//    // Get width, height, and depth of texture
//    *iWidth = tgaHeader.width;
//    *iHeight = tgaHeader.height;
//    sDepth = tgaHeader.bits / 8;
//    
//    // Put some validity checks here. Very simply, I only understand
//    // or care about 8, 24, or 32 bit targa's.
//    if(tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32)
//        return NULL;
//	
//    // Calculate size of image buffer
//    lImageSize = tgaHeader.width * tgaHeader.height * sDepth;
//    
//    // Allocate memory and check for success
//    pBits = (GLbyte*)malloc(lImageSize * sizeof(GLbyte));
//    if(pBits == NULL)
//        return NULL;
//    
//    // Read in the bits
//    // Check for read error. This should catch RLE or other 
//    // weird formats that I don't want to recognize
//    if(fread(pBits, lImageSize, 1, pFile) != 1)
//		{
//        free(pBits);
//        return NULL;
//		}
//    
//    // Set OpenGL format expected
//    switch(sDepth)
//		{
//		case 3:     // Most likely case
//				*eFormat = GL_BGR;
//				*iComponents = GL_RGB;
//				break;			
//
//        case 4:
//            *eFormat = GL_BGRA;
//            *iComponents = GL_RGBA;
//            break;
//        case 1:
//            *eFormat = GL_LUMINANCE;
//            *iComponents = GL_LUMINANCE;
//            break;
//		};
//	
//    
//    // Done with File
//    fclose(pFile);
//	
//    // Return pointer to image data
//    return pBits;
//}
char *ReadTGABitsFromMemory(void *pData, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat)
{
	//FILE *pFile;			// File pointer
    TGAHEADER tgaHeader;		// TGA file header
    unsigned long lImageSize;		// Size in bytes of image
    short sDepth;			// Pixel depth;
    char	*pBits = NULL;          // Pointer to bits
    
    // Default/Failed values
    *iWidth = 0;
    *iHeight = 0;
    *eFormat = GL_RGB;
    *iComponents = GL_RGB;
    
    // Attempt to open the fil
    //pFile = fopen(szFileName, "rb");
    //if(pFile == NULL)
    //    return NULL;
	
    // Read in header (binary)
    //fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, pFile);
	memcpy(&tgaHeader, pData, 18);
	
    // Get width, height, and depth of texture
    *iWidth = tgaHeader.width;
    *iHeight = tgaHeader.height;
    sDepth = tgaHeader.bits / 8;
    
    // Put some validity checks here. Very simply, I only understand
    // or care about 8, 24, or 32 bit targa's.
    if(tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32)
        return NULL;
	
    // Calculate size of image buffer
    lImageSize = tgaHeader.width * tgaHeader.height * sDepth;
    
    // Allocate memory and check for success
    pBits = (char*)malloc(lImageSize * sizeof(GLbyte));
    if(pBits == NULL)
        return NULL;
    

    // Read in the bits
    // Check for read error. This should catch RLE or other 
    // weird formats that I don't want to recognize
   /* if(fread(pBits, lImageSize, 1, pFile) != 1)
		{
        free(pBits);
        return NULL;
		}*/

	memcpy(pBits, pData, lImageSize);
    
    // Set OpenGL format expected
    switch(sDepth)
		{
		case 3:     // Most likely case
				*eFormat = GL_BGR;
				*iComponents = GL_RGB;
				break;			

        case 4:
            *eFormat = GL_BGRA;
            *iComponents = GL_RGBA;
            break;
        case 1:
            *eFormat = GL_LUMINANCE;
            *iComponents = GL_LUMINANCE;
            break;
		};
	
    
    // Done with File
   // fclose(pFile);
	
    // Return pointer to image data
    return pBits;
}

bool LoadTGA(const char *szFile, int &nHeight, int &nWidth)
{
	GLint iComp;
	GLenum eFormat;
	GLbyte *pData = gltReadTGABits(szFile, &nWidth, &nHeight, &iComp, &eFormat);
	if (!pData)
		return false;

	glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	glTexImage2D(GL_TEXTURE_2D, 0, iComp, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pData);
	free(pData);

	return true;
}

bool LoadTGAFromMemory(char *pData, int &nHeight, int &nWidth)
{
	GLint iComp;
	GLenum eFormat;
	char *pImgData = ReadTGABitsFromMemory(pData, &nWidth, &nHeight, &iComp, &eFormat);
	if (!pData)
		return false;

	glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	glTexImage2D(GL_TEXTURE_2D, 0, iComp, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pImgData);
	free(pImgData);

	return true;
}

#endif